// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

#include "DBManager/Service/Input/Property/PropertySummaryService.h"

#include <cassert>
#include <list>

#include "DataStructure/Common/Id.h"
#include "DataStructure/Input/Property/PropertyTypes.h"

#include "DBManager/Common/ServiceMacro.h"
#include "DBManager/IRepository/Input/Property/IPropertySummaryRepository.h"
#include "DBManager/Service/Input/Property/PropertySummaryService.h"
using namespace SG::DBManager;

SERVICE_REG_FOR_SUMMARY (PropertySummaryService, IPropertySummaryRepository)

namespace
{
    std::vector<PropertySummaryService::SummaryCreateService>* g_summaryCreatePropService = nullptr;
}

PropertySummaryService::PropertySummaryService (DBServiceFactory* const dbServiceFactory, IPropertySummaryRepository& repos)
    : InputServiceBase<IPropertySummaryRepository> (dbServiceFactory, repos)
{}

PropertySummaryService::~PropertySummaryService () = default;

SG::DataStructure::FEM::PropertyTypes PropertySummaryService::GetPropertyType (SG::DataStructure::Common::Id id)
{
    return m_repository.GetPropertyType (id);
}

SG::DataStructure::Common::Status PropertySummaryService::CopyData (DBServiceFactory* const                    dest,
                                                                    std::vector<SG::DataStructure::Common::Id> ids)
{
    std::map<std::size_t, std::list<SG::DataStructure::Common::Id>> map;
    for (auto&& id : ids)
    {
        auto        type   = GetPropertyType (id);
        std::size_t typeId = typeid (decltype (type)).hash_code () + type;

        if (map.find (typeId) == map.end ())
        {
            map[typeId] = std::list<SG::DataStructure::Common::Id> ();
        }
        map[typeId].push_back (id);
    }

    auto funMap = m_dbServiceFactory->GetDatabase ()->GetHub()->CopyDataFunMap ();
    for (auto&& pair : map)
    {
        if (funMap.count (pair.first) > 0)
        {
            funMap[pair.first](m_dbServiceFactory, dest, { pair.second.begin (), pair.second.end () });
        }
    }

    return SG::DataStructure::Common::Status::STATUS_Success;
}

bool PropertySummaryService::RegisterService (SummaryCreateService&& service)
{
    if (g_summaryCreatePropService == nullptr)
        ::g_summaryCreatePropService = new std::vector<SummaryCreateService> ();

    ::g_summaryCreatePropService->emplace_back (std::move (service));
    return true;
}

void PropertySummaryService::CreateSummary (DBServiceFactory* const dbServiceFactory)
{
    for (size_t i = 0; i < g_summaryCreatePropService->size (); i++)
    {
        g_summaryCreatePropService->at (i) (dbServiceFactory);
    }
}
